package com.tencent.welink.util;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.FileEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.File;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;

/**
 * Created by junchihe on 2019/7/29.
 */
public class HttpPoolUtils {

    private static final Logger log = LogManager.getLogger(HttpPoolUtils.class);
    // 池化管理
    private static PoolingHttpClientConnectionManager poolConnManager = null;

    public static CloseableHttpClient httpClient;
    //请求器的配置
    private static RequestConfig requestConfig;

    static {
        try {
            log.info("begin to initial Http redis Pool client pool...");
            SSLContextBuilder builder = new SSLContextBuilder();
            builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                    builder.build());
            // 配置同时支持 HTTP 和 HTPPS
            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create().register(
                    "http", PlainConnectionSocketFactory.getSocketFactory()).register(
                    "https", sslsf).build();
            // 初始化连接管理器
            poolConnManager = new PoolingHttpClientConnectionManager(
                    socketFactoryRegistry);
            // 将最大连接数增加到200，实际项目最好从配置文件中读取这个值
            poolConnManager.setMaxTotal(200);
            // 设置最大路由
            poolConnManager.setDefaultMaxPerRoute(5);
            // 根据默认超时限制初始化requestConfig
            int socketTimeout = 10000;
            int connectTimeout = 10000;
            int connectionRequestTimeout = 10000;
            requestConfig = RequestConfig.custom().setConnectionRequestTimeout(
                    connectionRequestTimeout).setSocketTimeout(socketTimeout).setConnectTimeout(
                    connectTimeout).build();

            // 初始化httpClient
            httpClient = getConnection();

            log.info("end to initial Http client pool...");
        } catch (NoSuchAlgorithmException e) {
            log.error(e);
        } catch (KeyStoreException e) {
            log.error(e);
        } catch (KeyManagementException e) {
            log.error(e);
        }
    }

    private static CloseableHttpClient getConnection() {
        CloseableHttpClient httpClient = HttpClients.custom()
                // 设置连接池管理
                .setConnectionManager(poolConnManager)
                // 设置请求配置
                .setDefaultRequestConfig(requestConfig)
                // 设置重试次数
                .setRetryHandler(new DefaultHttpRequestRetryHandler(3, false))
                .build();

        if (poolConnManager != null && poolConnManager.getTotalStats() != null)
        {
            log.info("now client pool "
                    + poolConnManager.getTotalStats().toString());
        }

        return httpClient;
    }

    public static String httpPut(String url,String fileName) {
        HttpPut httpPut = new HttpPut(url);
        CloseableHttpResponse response = null;
        for(int i=0;i<total;i++) {
            try {
                File file = new File(fileName);
                if (!file.isFile())
                    return null;
                httpPut.setEntity(new FileEntity(file, ContentType.APPLICATION_OCTET_STREAM));
                response = httpClient.execute(httpPut);
                HttpEntity entity = response.getEntity();
                String result = EntityUtils.toString(entity, "utf-8");
                EntityUtils.consume(entity);
                ;
                return result;
            } catch (IOException e) {
                log.error("post retry for ["+i+"] times",e);
                if(i+1<total) {
                    try {
                        Thread.sleep(5000);
                    } catch (Exception e1) {
                        log.error(e1);
                    }
                }
            } finally {
                try {
                    if (response != null)
                        response.close();
                } catch (IOException e) {
                    log.error(e);
                }
            }
        }
        return null;
    }


    public static String httpPost(String url, String content, ContentType contentType,Header[] headers) {
        HttpPost httpPost = new HttpPost(url);
        CloseableHttpResponse response = null;
        if(headers != null){
            httpPost.setHeaders(headers);
        }
        for(int i=0;i<total;i++) {
            try {
                if (StringUtils.isNotBlank(content))
                    httpPost.setEntity(new StringEntity(content, contentType));
                response = httpClient.execute(httpPost);
                HttpEntity entity = response.getEntity();
                String result = EntityUtils.toString(entity, "utf-8");
                EntityUtils.consume(entity);
                ;
                return result;
            } catch (IOException e) {
                log.error("post retry for ["+i+"] times",e);
                if(i+1<total) {
                    try {
                        Thread.sleep(5000);
                    } catch (Exception e1) {
                        log.error(e1);
                    }
                }
            } finally {
                try {
                    if (response != null)
                        response.close();
                } catch (IOException e) {
                    log.error(e);
                }
            }
        }
        return null;
    }


    public static String httpPost(String url, byte[] content, ContentType contentType,Header[] headers) {
        HttpPost httpPost = new HttpPost(url);
        CloseableHttpResponse response = null;
        if(headers != null){
            httpPost.setHeaders(headers);
        }
        for(int i=0;i<total;i++) {
            try {
                httpPost.setEntity(new ByteArrayEntity(content, contentType));
                response = httpClient.execute(httpPost);
                HttpEntity entity = response.getEntity();
                String result = EntityUtils.toString(entity, "utf-8");
                EntityUtils.consume(entity);
                ;
                return result;
            } catch (IOException e) {
                log.error("post retry for ["+i+"] times",e);
                if(i+1<total) {
                    try {
                        Thread.sleep(5000);
                    } catch (Exception e1) {
                        log.error(e1);
                    }
                }
            } finally {
                try {
                    if (response != null)
                        response.close();
                } catch (IOException e) {
                    log.error(e);
                }
            }
        }
        return null;
    }


    private static final int total = 3;

    public static String httpGet(String url,Header[] headers) {
        HttpGet httpGet = new HttpGet(url);
        if(headers != null){
            httpGet.setHeaders(headers);
        }
        CloseableHttpResponse response = null;
        for(int i=0;i<total;i++) {
            try {
                response = httpClient.execute(httpGet);
                HttpEntity entity = response.getEntity();
                String result = EntityUtils.toString(entity, "utf-8");
                EntityUtils.consume(entity);
                return result;
            } catch (IOException e) {
                log.error("get retry for ["+i+"] times",e);
                if(i+1<total) {
                    try {
                        Thread.sleep(5000);
                    } catch (Exception e1) {
                        log.error(e1);
                    }
                }
            } finally {
                try {
                    if (response != null)
                        response.close();
                } catch (IOException e) {
                    log.error(e);
                }
            }
        }
        return null;
    }

    public static byte[]  httpGetByteArray(String url,Header[] headers) {
        HttpGet httpGet = new HttpGet(url);
        if(headers != null){
            httpGet.setHeaders(headers);
        }
        CloseableHttpResponse response = null;
        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(50000).setConnectionRequestTimeout(50000).setSocketTimeout(50000).build();
        httpGet.setConfig(requestConfig);
        for(int i=0;i<total;i++) {
            try {
                response = httpClient.execute(httpGet);
                HttpEntity entity = response.getEntity();
                byte[]  result = EntityUtils.toByteArray(entity);
                EntityUtils.consume(entity);
                return result;
            } catch (IOException e) {
                log.error("get retry for ["+i+"] times",e);
                if(i+1<total) {
                    try {
                        Thread.sleep(5000);
                    } catch (Exception e1) {
                        log.error(e1);
                    }
                }
            } finally {
                try {
                    if (response != null)
                        response.close();
                } catch (IOException e) {
                    log.error(e);
                }
            }
        }
        return null;
    }

   /* public String getCameraInfo(long din) {

    }*/


   public static void main(String[] args) {
       /**
        a.请求头：Content-Type:application/json
        b.请求包体:{
        "apiName": "report_data_point",
        "cookie": "16198_577418",
        "wId": "********",
        "errmsg": "",
        "id": 20134,
        "time": 1511802600575,
        "type": "string",
        "value":"{\"V\":1,\"subid\":\"0900009\",\"list\":[{\"func\":\"CO2\",\"value\":\"972180.00\"}],\"timestamp\":1511802557768}",
        "seq": "0"
        }

        */
       String bodyData = "{\"apiName\": \"report_data_point\"," +
               "\"cookie\": \"16998_579418\"," +
               "\"din\": \"1323232\"," +
               "\"errmsg\": \"\"," +
               "\"id\": 20134," +
               "\"time\": 1511802600575," +
               "\"type\": \"string\"," +
               "\"value\":\"{\\\"V\\\":1,\\\"subid\\\":\\\"0900009\\\",\\\"list\\\":[{\\\"func\\\":\\\"CO2\\\",\\\"value\\\":\\\"972180.00\\\"}],\\\"timestamp\\\":1511802557768}\"," +
               "\"seq\": \"0\"}";
       String back = HttpPoolUtils.httpPost("http://123.206.207.132:8844/welink/callback",bodyData,ContentType.APPLICATION_JSON,null);
       System.out.println(back);
   }
}
